package cn.dt.basic.service.impl;

import cn.dt.basic.constant.BaseConstants;
import cn.dt.basic.dto.RegisterDto;
import cn.dt.basic.dto.WechatDto;
import cn.dt.basic.exception.BusinessException;
import cn.dt.basic.service.ILoginService;
import cn.dt.basic.dto.LoginDto;
import cn.dt.basic.util.*;
import cn.dt.user.domain.Logininfo;
import cn.dt.user.domain.User;
import cn.dt.user.domain.Wxuser;
import cn.dt.user.mapper.LogininfoMapper;
import cn.dt.user.mapper.UserMapper;
import cn.dt.user.mapper.WxuserMapper;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private UserMapper userMapper;
    /**
     * 员工登录
     * 1.判断参数是否为空，为空提示
     * 2.根据账号，手机号，邮箱查询是否有此员工
     *  2.1 没有查询到则提示
     * 3.判断密码是否一致，此处要将密码进行md5加密加盐以后进行再做判断是否一致
     *  3.1不一致提醒
     * 登录成功
     * 4.将此员工信息保存到redis，但是密码，盐值是重要信息，要设置为空再保存redis
     * 5.返回token和此对象给前端
     * @param dto
     */
    @Override
    public Map<String, Object> account(LoginDto dto) {
        String username = dto.getUsername();
        String password = dto.getPassword();
        Integer type = dto.getType();
        //* 1.判断参数是否为空，为空提示
        if(
                StringUtils.isEmpty(username)||
                StringUtils.isEmpty(password)
        ){
            throw new BusinessException("填入的信息不能为空！");
        }
        //* 2.根据账号（账号，手机号，邮箱）和类型查询是否有此员工
        Logininfo logininfo = logininfoMapper.loadByUsernameAndType(username,type);
        //*  2.1 没有查询到则提示
        if(logininfo==null){
            throw new BusinessException("您输入的账号有误");
        }
        //* 3.判断密码是否一致，此处要将密码进行md5加密加盐以后进行再做判断是否一致
        String salt = logininfo.getSalt();
        String passwordTmp = MD5Utils.encrypByMd5(password + salt);
        //*  3.1不一致提醒
        if(!passwordTmp.equals(logininfo.getPassword())){
            throw new BusinessException("密码不正确");
        }
        //* 登录成功
        //* 4.将此员工信息保存到redis，但是密码，盐值是重要信息，要设置为空再保存redis
        //注意：用redis保存对象需要序列化
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(
                token,
                logininfo,
                30,
                TimeUnit.MINUTES
        );
        //* 5.返回token和此对象给前端
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("logininfo",logininfo);
        return map ;
    }

    /**
     * 微信三方登录第二步，
     * 1.用户扫码之后，通过code去TOKEN_URL这个网址获取token和openid
     * 2.通过openid查询wxuser表是否存在
     *  2,1存在，直接登录
     *  2.2，不存在则跳转到注册界面
     * @param dto
     * @return
     */
    @Override
    public AjaxResult wechat(WechatDto dto) {
        String tokenUrl = BaseConstants.WeChart.TOKEN_URL
                .replace("APPID",BaseConstants.WeChart.APPID)
                .replace("SECRET",BaseConstants.WeChart.SECRET)
                .replace("CODE",dto.getCode());

        //将网址中对应的appid，secret，code替换
//        tokenUrl.replace("APPID",appId);
//        tokenUrl.replace("SECRET",secret);
//        tokenUrl.replace("CODE",code);
        String getTokenstr = HttpClientUtils.httpGet(tokenUrl);
        //将字符串形式的getTokenstr解析成json格式
        JSONObject jsonObject = JSONObject.parseObject(getTokenstr);
        //获取到token
        String accessToken = jsonObject.getString("access_token");
        String openId = jsonObject.getString("openid");
        //2.通过openid查询wxuser表是否存在
        Wxuser wxuser = wxuserMapper.loadByOpenid(openId);
        // 2,1存在，直接登录
        //2.通过wxuser表
        if(wxuser!=null &&wxuser.getUserId()!=null){
            Logininfo logininfo = logininfoMapper.loadByUserId(wxuser.getUserId());
            //4.1 存储redis
            String token = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set(
                    token,
                    logininfo,//对象要序列化
                    30,
                    TimeUnit.MINUTES
            );
            //4.2 返回token + logininfo
            Map<String, Object> map = new HashMap<>();
            map.put("token",token);
            //我们是高级技师，应该考虑到一些敏感信息不要返回给前端
            logininfo.setSalt(null);
            logininfo.setPassword(null);
            map.put("logininfo",logininfo);
            return AjaxResult.me().setResultObj(map);
        }
        // 2.2，不存在则跳转到注册界面,网页要带token+openid
        String binderParam = "?accessToken="+accessToken+"&openId="+openId;
        return AjaxResult.me().setSuccess(false).setResultObj(binderParam);

    }

    /**
     * 微信三方登录注册绑定
     * 1.根据手机号查询是否有此user用户
     * 1.1有此用户就等待绑定，
     * 2.不存在就进行user和loginfor对象的创建
     * 3.从微信获取用户的基本信息（用工具类发送get请求，返回的是json格式字符串，需要转换成对象进行操作）
     * 4.将wxuser表中的user_id和user表中的id进行绑定
     * 5.创建wxuser对象
     * 6.免密登录到主页
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> binder(WechatDto dto) {
        //* 1.根据手机号查询是否有此user用户
        User user = userMapper.loadByPhone(dto.getPhone());
        Logininfo logininfo = null;
        //* 1.1有此用户就等待绑定，
        if(user!=null){
            Wxuser wxuser =wxuserMapper.loadbyuserid(user.getId());
            if(wxuser!=null){
                throw new BusinessException("该手机号已经绑定微信，请更换手机号！！");
            }
           logininfo = logininfoMapper.loadById(user.getLogininfoId());

        }else{
            //* 2.不存在就进行user和loginfor对象的创建
            //* 5.保存user表和loginfo表
            //将前端获取到的所有字段对象转换成user对象
            user = dto2User(dto);
            logininfo = user2Logininfo(user);
            logininfoMapper.save(logininfo);
            user.setLogininfoId(logininfo.getId());
            userMapper.save(user);
        }
        //* 3.从微信获取用户的基本信息（用工具类发送get请求，返回的是json格式字符串，需要转换成对象进行操作）
        System.out.println(dto.getAccessToken());
        System.out.println(dto.getOpenId());
        String wxuserUrl = BaseConstants.WeChart.WXUSER_URL
                .replace("ACCESS_TOKEN",dto.getAccessToken())
                .replace("OPENID",dto.getOpenId());
        String wxuserStr = HttpClientUtils.httpGet(wxuserUrl);
        //将返回的微信用户基本信息字符串转换成Wxuser累心的对象
        Wxuser wxuser = JSONObject.parseObject(wxuserStr, Wxuser.class);

        //* 4.将wxuser表中的user_id和user表中的id进行绑定
        wxuser.setUserId(user.getId());
        //* 5.创建wxuser对象
        wxuserMapper.save(wxuser);
        //* 6.免密登录到主页
        logininfo = logininfoMapper.loadByUserId(wxuser.getUserId());
        //4.1 存储redis
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(
                token,
                logininfo,//对象要序列化
                30,
                TimeUnit.MINUTES
        );
        //4.2 返回token + logininfo
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        //我们是高级技师，应该考虑到一些敏感信息不要返回给前端
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        map.put("logininfo",logininfo);
        return map;

    }
    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(0);
        return logininfo;
    }

    private User dto2User(WechatDto dto) {
        User user = new User();
        user.setUsername(dto.getPhone());
        user.setPhone(dto.getPhone());
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = MD5Utils.encrypByMd5(dto.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        return user;
    }

}
